/*
	Copyright (C) 2011 Daniel C. Dennison (dandennison84@gmail.com).  All rights reserved.
	This file is licensed under the EPL 1.0 (Eclipse Public License 1.0)
	A copy of the license can be found at http://www.eclipse.org/legal/epl-v10.html
*/

package com.gmail.dandennison84.accounting

class Account implements Comparable {
	final String name
	boolean contra
	Account contraAccount
	String groupName
	final AccountType accountType
	final BalanceType balanceType
	final ClosingType closingType
	final CashFlowStatementType cashFlowStatementType
	final Map properties = [:]
	final List<JournalEntry> entries = []

	Account(Map map) {
		name = map['name']
		groupName = map['groupName']
		accountType = map['accountType']
		balanceType = map['balanceType']
		closingType = map['closingType']
		cashFlowStatementType = map['cashFlowStatementType']
		contraAccount = map['contraAccount']
		contra = contraAccount ? false : map['contra']?:false
		Map p = map['properties']
		if(p) {
			properties.putAll(p)
		}

		assert name
		assert accountType
		assert balanceType
		assert closingType
		assert cashFlowStatementType
	}

	List<JournalEntry> getEntriesOn(Date date) {
		date ? entries.findAll {it.dateTime == date} : entries
	}

	List<JournalEntry> getEntriesFrom(Date from) {
		from ? entries.findAll {it.dateTime >= from} : entries
	}

	List<JournalEntry> getEntriesTo(Date to) {
		to ? entries.findAll {it.dateTime <= to} : entries
	}

	List<JournalEntry> getEntriesBetween(Date from, Date to) {
		if(!from) {
			getEntriesTo(to)
		} else if(!to) {
			getEntriesFrom(from)
		} else {
			entries.findAll {it.dateTime >= from && it.dateTime <= to}
		}
	}

	double getDebitBalanceOn(Date date) {
		sumDebits(getEntriesOn(date))
	}

	double getDebitBalanceFrom(Date from) {
		sumDebits(getEntriesFrom(from))
	}

	double getDebitBalanceTo(Date to) {
		sumDebits(getEntriesTo(to))
	}

	double getDebitBalanceBetween(Date from, Date to) {
		sumDebits(getEntriesBetween(from, to))
	}

	double getDebitBalance() {
		sumDebits(entries)
	}

	double getCreditBalanceOn(Date date) {
		sumCredits(getEntriesOn(date))
	}

	double getCreditBalanceFrom(Date from) {
		sumCredits(getEntriesFrom(from))
	}

	double getCreditBalanceTo(Date to) {
		sumCredits(getEntriesTo(to))
	}

	double getCreditBalanceBetween(Date from, Date to) {
		sumCredits(getEntriesBetween(from, to))
	}

	double getCreditBalance() {
		sumCredits(entries)
	}

	int compareTo(other) {
		name <=> other.name
	}

	String toString() {
		String s1 = "$name [contra: $contra, accountType: $accountType, balanceType: $balanceType, closingType: $closingType, groupName: $groupName, "
		s1 + "contraAccount: ${contraAccount?.name}, properties: $properties]"
	}

	private double sumDebits(List<JournalEntry> l) {
		l.inject(0) {acc, it -> acc + it.findDebitAmountByName(name)}
	}

	private double sumCredits(List<JournalEntry> l) {
		l.inject(0) {acc, it -> acc + it.findCreditAmountByName(name)}
	}
}
